package com.flame.workflow.ru.engine.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.flame.core.id.IdWorker;
import com.flame.core.utils.DateUtils;
import com.flame.workflow.constants.NodeConstants;
import com.flame.workflow.constants.RuntimeConstants;
import com.flame.workflow.constants.TaskConstants;
import com.flame.workflow.re.entity.Node;
import com.flame.workflow.re.service.NodeService;
import com.flame.workflow.ru.engine.context.RuntimeContext;
import com.flame.workflow.ru.entity.Instance;
import com.flame.workflow.ru.entity.Task;
import com.flame.workflow.ru.mapper.TaskCommentMapper;
import com.flame.workflow.ru.service.TaskPropertyService;
import com.flame.workflow.ru.service.TaskService;
import com.flame.workflow.ru.service.UserTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;

/**
 * @author wuxintong😺😺😺
 * @since 2023/6/6
 */
public abstract class AbstractTaskHandler implements TaskHandler {

    @Autowired
    protected ApplicationEventPublisher publisher;

    @Autowired
    protected NodeService nodeService;

    @Autowired
    protected TaskService taskService;

    @Autowired
    protected TaskPropertyService taskPropertyService;

    @Autowired
    protected IdWorker idWorker;

    @Autowired
    protected ObjectMapper objectMapper;

    @Autowired
    protected UserTaskService userTaskService;

    @Autowired
    protected TaskCommentMapper taskCommentMapper;

    @Override
    public Task startTask(RuntimeContext runtimeContext) {
        Instance instance = runtimeContext.getInstance();
        Task parentTask = runtimeContext.getTask();
        Node node = runtimeContext.getNode();

        long taskId = idWorker.nextId();
        Task task = new Task();
        task.setInstanceId(instance.getInstanceId());
        task.setTaskId(taskId);
        task.setTaskName(node.getNodeName());
        task.setTaskType(node.getNodeType());
        task.setNodeId(node.getNodeId());
        task.setParentTaskId(parentTask.getTaskId());
        if (TaskConstants.TASK_TYPE_CONDITION.equals(parentTask.getTaskType()) ||
                TaskConstants.TASK_TYPE_PARALLEL.equals(parentTask.getTaskType())) {
            if (NodeConstants.NODE_TYPE_CONDITION_BRANCH.equals(node.getNodeType()) ||
                    NodeConstants.NODE_TYPE_PARALLEL_BRANCH.equals(node.getNodeType())) {
                task.setBranchTaskId(parentTask.getTaskId());
            } else {
                task.setBranchTaskId(parentTask.getBranchTaskId());
            }
        } else if (TaskConstants.TASK_TYPE_CONDITION_BRANCH.equals(parentTask.getTaskType()) ||
                TaskConstants.TASK_TYPE_PARALLEL_BRANCH.equals(parentTask.getTaskType())) {
            task.setBranchTaskId(parentTask.getTaskId());
        } else {
            task.setBranchTaskId(parentTask.getBranchTaskId());
        }
        task.setTaskStatus(RuntimeConstants.RUNTIME_STATUS_CREATE);
        task.setCreateTime(DateUtils.currentDateTime());
        taskService.addTask(task);
        taskPropertyService.addTaskProperty(instance.getInstanceId(), taskId, node.getNodeProperties());
        task.setTaskProperties(node.getNodeProperties());
        return task;
    }

    @Override
    public String runTask(RuntimeContext runtimeContext) {
        return RuntimeConstants.RUNTIME_STATUS_COMPLETE;
    }

    @Override
    public void finishTask(RuntimeContext runtimeContext) {
    }

    @Override
    public boolean handleError(RuntimeContext runtimeContext) {
        return true;
    }

    @Override
    public String taskType() {
        return TaskConstants.TASK_TYPE_DEFAULT;
    }
}
